use base_data::channel::EndReason;
use std::fmt::Debug;
use tools::enum_generator;
use tracing::error;

// pub(crate) mod codec;
pub mod config;
pub(crate) mod dialog;
pub(crate) mod distribute;
pub(crate) mod head;
pub mod register;
pub(crate) mod transport;
pub(crate) mod utils;

///此为sip逻辑的管理..
///
/// 可以通过调用listen_device()方法增加监听地址.
/// 第一次调用listen_device()方法.会生成一个协程,并且一直存在.
/// 此协程用来将sip消息与业务逻辑消息进行转换,
/// 每次新增加一个dialog时,将再生成一个协程,用来处理这个dialog的逻辑.但不增加协程用于处理事务
/// 需要进行会话时,会再生成一个协程用来处理会话方面.
pub mod manage;

pub const SIP_VERSION: &[u8] = b"SIP/2.0";
pub const SIP_VERSION_SUFFIX: &[u8] = b"SIP/2.0/";
///一般分隔符
pub const SEPARATOR: &[u8] = b" ";
///分隔符: 分号
pub const SEMICOLON: &[u8] = b";";
pub const DOUBLE_QUOTATION: &[u8] = b"\"";
///sip url前缀
pub const SIP_URL_PREFIX: &[u8] = b"<sip:";
pub const TAG_PREFIX: &[u8] = b";tag=";
///sip url的后缀
pub const SIP_URL_SUFFIX: &[u8] = b">";
///branch字符,带魔数
pub const BRANCH_CHAR: &[u8] = b";branch=z9hG4bK";
///头字段的分隔符.此分隔符带冒号和空格
pub const HEAD_SEPARATOR: &[u8] = b": ";
pub const CRLF: &[u8] = b"\r\n";

#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub(crate) enum SipMethod {
	Invite,
	Ack,
	Prack,
	Cancel,
	Bye,
	Register,
	Options,
	Info,
	Notify,
	Subscribe,
	Publish,
	Message,
	Update,
	Unknown,
}

enum_generator! {
	;
	SipResponse{
		Try("SIP/2.0 100 Trying",100),
		Ringing("SIP/2.0 180 Ringing",180),
		CallIsBeingForwarded("SIP/2.0 181 Call Is Being Forwarded",181),
		///被呼SIP/2.0 叫方暂时不可用，但是服务器已确定将该呼叫转入等待队列
		Queued("SIP/2.0 182 Queued",182),
		SessionProgress("SIP/2.0 183 Session Progress",183),
		Ok("SIP/2.0 200 OK",200),
		MultipleChoices("SIP/2.0 300 Multiple Choices",300),
		MovedPermanently("SIP/2.0 301 Moved Permanently",301),
		MovedTemporarily("SIP/2.0 302 Moved Temporarily",302),
		UseProxy("SIP/2.0 305 Use Proxy",305),
		AlternativeService("SIP/2.0 380 Alternative Service",380),
		BadRequest("SIP/2.0 400 Bad Request",400),
		Unauthorized("SIP/2.0 401 Unauthorized",401),
		PaymentRequired("SIP/2.0 402 Payment Required",402),
		Forbidden("SIP/2.0 403 Forbidden",403),
		NotFound("SIP/2.0 404 Not Found",404),
		MethodNotAllowed("SIP/2.0 405 Method Not Allowed",405),
		NotAcceptable406("SIP/2.0 406 Not Acceptable",406),
		ProxyAuthenticationRequired("SIP/2.0 407 Proxy Authentication Required",407),
		RequestTimeout("SIP/2.0 408 Request Timeout",408),
		Conflict("SIP/2.0 409 Conflict",409),
		Gone("SIP/2.0 410 Gone",410),
		LengthRequired("SIP/2.0 411 Length Required",411),
		PreconditionFailed("SIP/2.0 412 Precondition Failed",412),
		RequestTooLong("SIP/2.0 414 Request-URI Too Long",414),
		UnsupportedMediaType("SIP/2.0 415 Unsupported Media Type",415),
		UnsupportedURIScheme("SIP/2.0 416 Unsupported URI Scheme",416),
		BadExtension("SIP/2.0 420 Bad Extension",420),
		ExtensionRequired("SIP/2.0 421 Extension Required",421),
		IntervalTooBrief("SIP/2.0 423 Interval Too Brief",423),
		TemporarilyUnavailable("SIP/2.0 480 Temporarily Unavailable",480),
		DoesNotExist("SIP/2.0 481 Call/Transaction Does Not Exist",481),
		LoopDetected("SIP/2.0 482 Loop Detected",482),
		TooManyHops("SIP/2.0 483 Too Many Hops",483),
		AddressIncomplete("SIP/2.0 484 Address Incomplete",484),
		Ambiguous("SIP/2.0 485 Ambiguous",485),
		BusyHere("SIP/2.0 486 Busy Here",486),
		RequestTerminated("SIP/2.0 487 Request Terminated",487),
		NotAcceptableHere("SIP/2.0 488 Not Acceptable Here",488),
		RequestPending("SIP/2.0 491 Request Pending",491),
		Undecipherable("SIP/2.0 493 Undecipherable",493),
		ServerInternalError("SIP/2.0 500 Server Internal Error",500),
		NotImplemented("SIP/2.0 501 Not Implemented",501),
		BadGateway("SIP/2.0 502 Bad Gateway",502),
		ServiceUnavailable("SIP/2.0 503 Service Unavailable",503),
		ServerTimeout("SIP/2.0 504 Gateway Time-out",504),
		VersionNotSupported("SIP/2.0 505 Version Not Supported",505),
		MessageTooLarge("SIP/2.0 513 Message Too Large",513),
		BusyEverywhere("SIP/2.0 600 Busy Everywhere",600),
		Decline("SIP/2.0 603 Decline",603),
		DoesNotExistAnywhere("SIP/2.0 604 Does Not Exist Anywhere",604),
		NotAcceptable606("SIP/2.0 606 Not Acceptable",606),
	}
}

impl From<&[u8]> for SipResponse {
	fn from(s: &[u8]) -> Self {
		match s {
			b"100" => SipResponse::Try,
			b"180" => SipResponse::Ringing,
			b"181" => SipResponse::CallIsBeingForwarded,
			b"182" => SipResponse::Queued,
			b"183" => SipResponse::SessionProgress,
			b"200" => SipResponse::Ok,
			b"300" => SipResponse::MultipleChoices,
			b"301" => SipResponse::MovedPermanently,
			b"302" => SipResponse::MovedTemporarily,
			b"305" => SipResponse::UseProxy,
			b"380" => SipResponse::AlternativeService,
			b"400" => SipResponse::BadRequest,
			b"401" => SipResponse::Unauthorized,
			b"402" => SipResponse::PaymentRequired,
			b"403" => SipResponse::Forbidden,
			b"404" => SipResponse::NotFound,
			b"405" => SipResponse::MethodNotAllowed,
			b"406" => SipResponse::NotAcceptable406,
			b"407" => SipResponse::ProxyAuthenticationRequired,
			b"408" => SipResponse::RequestTimeout,
			b"409" => SipResponse::Conflict,
			b"410" => SipResponse::Gone,
			b"411" => SipResponse::LengthRequired,
			b"412" => SipResponse::PreconditionFailed,
			b"414" => SipResponse::RequestTooLong,
			b"415" => SipResponse::UnsupportedMediaType,
			b"416" => SipResponse::UnsupportedURIScheme,
			b"420" => SipResponse::BadExtension,
			b"421" => SipResponse::ExtensionRequired,
			b"423" => SipResponse::IntervalTooBrief,
			b"480" => SipResponse::TemporarilyUnavailable,
			b"481" => SipResponse::DoesNotExist,
			b"482" => SipResponse::LoopDetected,
			b"483" => SipResponse::TooManyHops,
			b"484" => SipResponse::AddressIncomplete,
			b"485" => SipResponse::Ambiguous,
			b"486" => SipResponse::BusyHere,
			b"487" => SipResponse::RequestTerminated,
			b"488" => SipResponse::NotAcceptableHere,
			b"491" => SipResponse::RequestPending,
			b"493" => SipResponse::Undecipherable,
			b"500" => SipResponse::ServerInternalError,
			b"501" => SipResponse::NotImplemented,
			b"502" => SipResponse::BadGateway,
			b"503" => SipResponse::ServiceUnavailable,
			b"504" => SipResponse::ServerTimeout,
			b"505" => SipResponse::VersionNotSupported,
			b"513" => SipResponse::MessageTooLarge,
			b"603" => SipResponse::Decline,
			b"600" => SipResponse::BusyEverywhere,
			b"604" => SipResponse::DoesNotExistAnywhere,
			b"606" => SipResponse::NotAcceptable606,
			_ => SipResponse::UnknownValue,
		}
	}
}

///通过挂断原因转换成sip响应码
impl From<EndReason> for SipResponse {
	fn from(s: EndReason) -> Self {
		match s {
			EndReason::NoCalledNum => Self::NotFound,
			_ => Self::TemporarilyUnavailable,
		}
	}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum SipDirection {
	Request(SipMethod),
	Response(SipResponse),
}

impl From<&[u8]> for SipMethod {
	fn from(s: &[u8]) -> Self {
		match s {
			b"INVITE" | b"invite" => SipMethod::Invite,
			b"REGISTER" | b"register" => SipMethod::Register,
			b"ack" | b"ACK" => SipMethod::Ack,
			b"bye" | b"BYE" => SipMethod::Bye,
			b"cancel" | b"CANCEL" => SipMethod::Cancel,
			b"options" | b"OPTIONS" => SipMethod::Options,
			b"subscribe" | b"SUBSCRIBE" => SipMethod::Subscribe,
			b"notify" | b"NOTIFY" => SipMethod::Notify,
			b"prack" | b"PRACK" => SipMethod::Prack,
			b"info" | b"INFO" => SipMethod::Info,
			b"publish" | b"PUBLISH" => SipMethod::Publish,
			b"message" | b"MESSAGE" => SipMethod::Message,
			b"update" | b"UPDATE" => SipMethod::Update,
			_ => SipMethod::Unknown,
		}
	}
}

impl SipMethod {
	///取对应的字符串值
	fn as_bytes(&self) -> &[u8] {
		match self {
			SipMethod::Invite => b"INVITE",
			SipMethod::Register => b"REGISTER",
			SipMethod::Ack => b"ACK",
			SipMethod::Bye => b"BYE",
			SipMethod::Cancel => b"CANCEL",
			SipMethod::Options => b"OPTIONS",
			SipMethod::Subscribe => b"SUBSCRIBE",
			SipMethod::Notify => b"NOTIFY",
			SipMethod::Prack => b"PRACK",
			SipMethod::Info => b"INFO",
			SipMethod::Publish => b"PUBLISH",
			SipMethod::Message => b"MESSAGE",
			SipMethod::Update => b"UPDATE",
			SipMethod::Unknown => {
				error!("不能为SipMethod::Unknown返回字符串..未知的sip方法");

				b""
			}
		}
	}
}
